package com.exam.api.common.utils;

import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author iaa
 * @Description
 * @Date 2024/5/27 下午12:22
 */
@Slf4j
@Component
public class RedissonClientUtil {

    @Resource
    private RedissonClient redissonClient;


    /**
     * 普通缓存获取
     *
     * @param key 键
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redissonClient.getBucket(key).get();
    }

    /**
     * 普通缓存放入
     * @param key 键
     * @param value 值
     * @return true成功 false失败
     */
    public boolean set(String key,Object value) {
        try {
            redissonClient.getBucket(key).set(value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     * 带时间缓存
     * @param key 键
     * @param value 值
     * @param time 时间(分钟) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean setMinute(String key, Object value, long time) {
        try {
            if (time > 0) {
                redissonClient.getBucket(key).set(value, Duration.ofMinutes(time));
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 带时间缓存
     * @param key 键
     * @param value 值
     * @param time 时间(分钟) time要大于0 如果time小于等于0 将设置无限期
     * @return true成功 false 失败
     */
    public boolean setDays(String key, Object value, long time) {
        try {
            if (time > 0) {
                redissonClient.getBucket(key).set(value, Duration.ofDays(time));
            } else {
                set(key, value);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }
    /**
     *
     * @param key
     */
    public void del(String key) {
        redissonClient.getBucket(key).delete();
    }

    //================================hash=================================
    /**
     * HashGet
     * @param key 键 不能为null
     */
    public Map<Object, Object> hget(String key){
        Set<Map.Entry<Object, Object>> entries = redissonClient.getMap(key).entrySet();
        Map<Object, Object> params = new HashMap<>();
        for (Map.Entry<Object, Object> entry : entries) {
            params.put(entry.getKey(), entry.getValue());
        }
        return params;
    }

    /**
     * HashGet
     * @param key 键 不能为null
     * @param item 项 不能为null
     */
    public Object hget(String key,String item){
        return redissonClient.getMap(key).get(item);
    }


    /**
     * 向 hash 表中放入数据,如果不存在将创建
     * @param key 键
     * @param item 项
     * @param value 值
     * @return true 成功 false失败
     */
    public boolean hset(String key,String item,Object value) {
        try {
            redissonClient.getMap(key).put(item, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    public boolean hset(String key, Map<String, String> params) {
        try {
            RMap<Object, Object> map = redissonClient.getMap(key);
            map.putAll(params);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除hash表中的值
     *
     * @param key  键 不能为null
     * @param item 项 可以使多个 不能为null
     */
    public void hdel(String key, Object... item) {
        redissonClient.getMap(key).remove(item);
    }

    public void hdel(String key) {
        redissonClient.getMap(key).delete();
    }



    @FunctionalInterface
    public interface LockAction {
        void execute() throws Exception;
    }

    /**
     * 尝试获取锁并执行操作。
     *
     * @param lockKey 锁的 Key
     * @param action  要执行的操作
     * @return 如果成功获取锁并执行，返回 true；否则返回 false。
     */
    public boolean tryExecute(String lockKey, LockAction action) {
        RLock lock = redissonClient.getLock(lockKey);
        if (lock.tryLock()) {
            try {
                action.execute();
                return true;
            } catch (Exception e) {
                throw new RuntimeException("执行锁定操作时发生异常: " + lockKey, e);
            } finally {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        } else {
            log.warn("未能获取到分布式锁 [{}], 任务被跳过。", lockKey);
            return false;
        }
    }
}
